#include "stdafx.h"
#include "SimpleMap.h"
#include "Element.h"

#include <fstream>
namespace Core
{
	namespace GameLogic
	{
		ActionListener::ActionListener():Base(&ActionListener::OnAction){}

		SimpleMap::SimpleMap(std::string filename,int Blockwidth,int BlockHeight)
			:blockwidth(Blockwidth),blockheight(BlockHeight)
		{
			std::ifstream in;
			try{
				in.open(filename.c_str());
			}
			catch(...)
			{
				string p="No such a file ";
				p+=filename;
				throw std::exception(p.c_str());
			}
			unsigned short data;
			int j;
			in>>j;
			width=j;
			in>>j;
			height=j;
			map.resize(width*height);
			for(int i=0;i<height;i++)
				for(int j=0;j<width;j++)
				{
					if(in.eof()) throw std::exception("No enough data");
					in>>data;
					int t=Base::MapInfo::PASS;
					if(data!=(int)(Base::MapInfo::BLOCK) && data!=(int)(Base::MapInfo::PASS) )
						throw std::exception("Not a proper data");
					MapInfo info((MapInfo::Info)data);
					map[i*width+j]=info;
				}
				mLogicMap.Init(this);
		}
		Size SimpleMap::GetBlockSize() 
		{
			return Size(blockwidth,blockheight);
		}
		Size SimpleMap::GetMapSize()
		{
			return Size(width*blockwidth,height*blockheight);
		}
		Size SimpleMap::GetMapSizeByBlock()
		{
			return Size(width,height);
		}
		Position SimpleMap::BlockPosition(const Position& p)
		{
			return Position(p.x / blockwidth,p.y / blockheight);
		}
		Position SimpleMap::GetGridPosition(const Position& p)
		{
			return Position(p.x / blockwidth * blockwidth,p.y / blockheight * blockwidth);
		}
		SimpleMap::MapInfo SimpleMap::GetInfo(const Position& p)
		{
			Position& t=BlockPosition(p);
			return map[t.y*width+t.x];
		}
		void SimpleMap::AddElement(Element* element)
		{
			Position& t=this->BlockPosition (element->GetPosition());
			map[t.y*width+t.x].element=element;
		}
		Element* SimpleMap::GetElement(const Core::Position& position)
		{
			Position& t=this->BlockPosition( position);
			return map[t.y*width+t.x].element;
		}
		void SimpleMap::OnAction(SourceType& source)
		{
			Position& pre=BlockPosition(source.GetPrePosition());
			Position& t=BlockPosition(source.GetPosition());
			map[pre.y*width+pre.x].element=0;
			map[t.y*width+t.x].element=&source;
		}
		Position SimpleMap::GetGridPositionFromBlockPosition (const Core::Position &p)
		{
			return Position(p.x*blockwidth,p.y*blockheight);
		}
		SimpleMap::LogicMap& SimpleMap::GetLogicMap()
		{
			return mLogicMap;
		}

		SimpleMap::LogicMap::LogicMap() 
		{}
		void SimpleMap::LogicMap::Init(SimpleMap* map)
		{
			mMap=map;
		}
		Size SimpleMap::LogicMap::GetMapSize()
		{
			return mMap->GetMapSizeByBlock();
		}
		void SimpleMap::LogicMap::AddElement(Element* element)
		{
			mMap->AddElement(element);
		}
		Element* SimpleMap::LogicMap::GetElement(const Position& p)
		{
			return mMap->map[p.y*mMap->width+p.x].element;
		}
		SimpleMap::MapInfo SimpleMap::LogicMap::GetInfo(const Position&p)
		{
			return mMap->map[p.y*mMap->width+p.x];
		}
		SimpleMap::LogicMap::LogicPart& SimpleMap::LogicMap::GetLogicMap()
		{
			return *this;
		}
	}
}